function defineActive(target, key, value) {
    observe(value)
    Object.defineProperty(target, key, {
        get: function () {
            console.log('更新视图')
            return value
        },
        set: function (newValue) {
            if (value !== newValue) {
                value = newValue;
                console.log('更新视图')
            }
            return newValue
        }
    })
}

let arrProto = Array.prototype;
let newArrProto = Object.create(arrProto);
['push', 'pop', 'shift', 'unshift', 'splice'].forEach(name => {
    newArrProto[name] = function () {
        console.log('更新视图')
        arrProto[name].call(this, ...arguments)
    }
})

function observe(obj = {}) {
    if (obj === null || typeof obj !== 'object') {
        return obj
    }

    if (obj instanceof Array) {
        obj.__proto__ = newArrProto
    }

    for (let key in obj) {
        defineActive(obj, key, obj[key])
    }
}

let data = {
    a: 1,
    b: '2',
    c: {
        d: '3'
    },
    nums: [1, 2, 4]
}

observe(data);

data.a = 2
data.b = 3

data.nums.push(3)